package com.zxd.interview.conrruentbook;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 公平锁和非公平锁对于获多线程的影响
 * @author Xander
 * @version v1.0.0
 * @Package : com.zxd.interview.conrruentbook
 * @Description : 公平锁和非公平锁对于获多线程的影响
 * @Create on : 2023/5/25 16:01
 **/
public class FairLock {


    public static void main(String[] args) {
        Printer printer = new Printer();
        new Thread(new Job(printer)).start();
        new Thread(new Job(printer)).start();
        new Thread(new Job(printer)).start();
        new Thread(new Job(printer)).start();
//        new Thread(new Job(printer)).start();
//        new Thread(new Job(printer)).start();

    }/**运行结果：
     公平锁结果如下：
     Thread-2开始打印
     Thread-1开始打印
     Thread-3开始打印
     Thread-0开始打印
     Thread-2正在进行第一次打印 需要 7秒
     Thread-3正在进行第一次打印 需要 9秒
     Thread-0正在进行第一次打印 需要 3秒
     Thread-1正在进行第一次打印 需要 2秒
     Thread-2正在进行第二次打印 需要 2秒
     Thread-3正在进行第二次打印 需要 8秒
     Thread-0正在进行第二次打印 需要 2秒
     Thread-1正在进行第二次打印 需要 6秒

     非公平锁结果：

     */

    /**
     * 模拟打印机
     */
    static class Printer {
        /**
         * 设置 true 为 公平锁, false 为非公平锁
         *
         */
        private Lock queueLock = new ReentrantLock(false);
        public void printJob(Object document){

            queueLock.lock();
            try {
                long duration = (long) (Math.random() * 10000);
                System.out.println(Thread.currentThread().getName()+"正在进行第一次打印 "+ "需要 "+(duration/1000)+ "秒");
                Thread.sleep(duration);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                queueLock.unlock();
            }

            // 模拟要打印两份数据
            queueLock.lock();
            try {
                long duration = (long) (Math.random() * 10000);
                System.out.println(Thread.currentThread().getName()+"正在进行第二次打印 "+ "需要 "+(duration/1000)+ "秒");
                Thread.sleep(duration);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                queueLock.unlock();
            }


        }
    }

    /**
     * 模拟打印任务，可以多线程
     */
    static class Job implements Runnable{

        private Printer printer;

        public Job(Printer printer){
            this.printer = printer;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"开始打印");
            printer.printJob(new Object());
        }
    }
}

